// -----------------------------------------------------------------------
//  <copyright file="EntityExtensions.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2024 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2024/12/18 20:21</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Mapping;

using OSharp.Data.Snows;


namespace DaprPlus.Domain.Entity;

public static class EntityExtensions
{
    /// <summary>
    /// 检测指定类型是否为<see cref="IEntity"/>实例类型
    /// </summary>
    /// <param name="type">要判断的类型</param>
    /// <returns></returns>
    public static bool IsEntityType(this Type type)
    {
        Check.NotNull(type, nameof(type));
        return typeof(IEntity).IsAssignableFrom(type);
    }

    /// <summary>
    /// 检测指定类型是否为<see cref="IAggregateRoot"/>实例类型
    /// </summary>
    /// <param name="type">要判断的类型</param>
    /// <returns></returns>
    public static bool IsAggregateRootType(this Type type)
    {
        Check.NotNull(type, nameof(type));
        return typeof(IAggregateRoot).IsAssignableFrom(type);
    }

    /// <summary>
    /// 判断指定实体是否已过期
    /// </summary>
    /// <param name="entity">要检测的实体</param>
    /// <returns></returns>
    public static bool IsExpired(this IExpiring entity)
    {
        Check.NotNull(entity, nameof(entity));
        var now = DateTime.Now;
        return entity.BeginTime != null && entity.BeginTime.Value > now || entity.EndTime != null && entity.EndTime.Value < now;
    }

    /// <summary>
    /// 检测并执行<see cref="ICreationTime"/>接口的逻辑
    /// </summary>
    public static TEntity CheckICreatedTime<TEntity>(this TEntity entity)
        where TEntity : IEntity
    {
        if (entity is not ICreationTime entity1)
        {
            return entity;
        }
        if (entity1.CreatedTime == default)
        {
            entity1.CreatedTime = DateTime.Now;
        }

        return (TEntity)entity1;
    }

    public static TEntity SetId<TEntity>(this TEntity entity)
        where TEntity : IEntity
    {
        if (entity.Id == 0)
        {
            entity.Id = IdHelper.NextId();
        }

        return entity;
    }

    public static async Task<TEntity> InsertOrUpdateAsync<TDto, TEntity>(this IRepository<TEntity> repository, TDto dto, CancellationToken token = default)
        where TDto : class, IDto
        where TEntity : class, IEntity, IAggregateRoot
    {
        var entity = await repository.FindAsync(dto.Id, token);
        if (entity == null)
        {
            entity = dto.MapTo<TEntity>();
            return await repository.InsertAsync(entity, token);
        }

        entity = dto.MapTo(entity);
        return await repository.UpdateAsync(entity, token);
    }
}
